package Day01;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class HDFSAPI_TEST {

    /**
     * 打印Hadooop地址值
     * IO的方式写代码
     *
     * @throws IOException
     */
    @Test
    public void initHDFS() throws IOException {

        //1.创建配置信息对象
        Configuration conf = new Configuration();

        //2.获取文件系统
        FileSystem fs = FileSystem.get(conf);
        //3.打印文件系统
        System.out.print(fs.toString());
    }


    /**
     * 上传代码
     */
    @Test
    public void putFileToHDFS() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        //F2可以快速的定位错误
        Configuration conf = new Configuration();

        //2.设置部分参数
        conf.set("dfs.replication", "2");
        //3.找到HDFS的地址
        FileSystem fileSystem = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");
        //4.上传本地Windows文件的路径
//        Path src = new Path("D:\\data\\demo1.txt");
        Path src = new Path("D:\\tools\\null\\null.sys");
//        Path src = new Path("D:\\tools\\Linux所用Jar包\\hadoop-2.7.2.rar");

        //5.要上传到HDFS的路径
        Path dst = new Path("hdfs://bigdata111:9000/");

        //6.以拷贝的方式上传从src到dst
        fileSystem.copyFromLocalFile(src, dst);
        //7.关闭
        fileSystem.close();
        System.out.print("Ok,上传完成了");
    }


    @Test
    public void getFileFromHDFS() throws URISyntaxException, IOException, InterruptedException {
        //1.获取配置
        Configuration conf = new Configuration();
        //2.获取hdfs连接
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000/"), conf, "root");
        //3.文件下载
//        Path dst = new Path("D:\\tools\\demoFile\\null.sys");
//        Path src = new Path("hdfs://bigdata111:9000/null.sys");
        Path dst = new Path("D:\\tools\\demoFile\\hadoop-2.7.2.rar");
        Path src = new Path("hdfs://bigdata111:9000/hadoop-2.7.2.rar");
        fs.copyToLocalFile(src, dst);
        fs.close();
        System.out.print("OK，下载完成");

    }


    /**
     * HDFS上面创建文件夹
     */
    @Test
    public void mkdirInHDFS() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.连接hdfs文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");
        //3.创建目录
        fs.mkdirs(new Path("hdfs://bigdata111:9000/Good"));

        //4.关闭
        fs.close();
    }

    /**
     * 删除文件
     */
    @Test
    public void delFileInHDFS() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.连接hdfs文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");
        //3.创建目录
//        fs.mkdirs(new Path("hdfs://bigdata111:9000/Good"));
        fs.delete(new Path("hdfs://bigdata111:9000/Good"), true);
        //4.关闭
        fs.close();
        System.out.println("删除完成");
    }

    /**
     * 文件详情
     */
    @Test
    public void searchFileDetail() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.连接hdfs文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");
        //3.创建目录
//        fs.mkdirs(new Path("hdfs://bigdata111:9000/Good"));

        RemoteIterator<LocatedFileStatus> listSFiles = fs.listFiles(new Path("hdfs://bigdata111:9000/"), true);

        while (listSFiles.hasNext()) {

            LocatedFileStatus fileStatus = listSFiles.next();

            //名字
            System.out.println(fileStatus.getPath().getName());
            //块大小
            System.out.println(fileStatus.getBlockLocations());
            //权限
            System.out.println(fileStatus.getPermission());
            //长度
            System.out.println(fileStatus.getLen());
        }
        //4.关闭
        fs.close();
        System.out.println("文件详情获取成功");
    }


    /**
     * 判断某目录下是文件还是目录
     */
    @Test
    public void judge() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.连接hdfs文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");

        //3.遍历所有的文件
        FileStatus[] listStatus = fs.listStatus(new Path("/"));
        for (FileStatus status : listStatus) {
            //判断是否是文件
            if (status.isFile()) {
                System.out.println("文件：" + status.getPath().getName());
            } else {
                System.out.println("目录：" + status.getPath().getName());
            }
        }
        System.out.println("查询完毕");
    }


    /**
     * 通过IO流方式传输文件到HDFS
     *
     * @throws URISyntaxException
     * @throws IOException
     * @throws InterruptedException
     */
    @Test
    public void putFileToHDFSByIo() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.连接hdfs文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");

        //3.创建IO流
        FileInputStream fis = new FileInputStream(new File("D:\\data\\Sogou.txt"));

        //4.创建目标地址
        //注意目标位置不能是个目录，需要文件的名字
        Path writePath = new Path("hdfs://bigdata111:9000/sougou.txt");
        FSDataOutputStream fos = fs.create(writePath);

        //5.流对接
        //InputStream       输入
        //OutputStream       输入
        //int bufsize       大小
        //boolean           是否关闭
        IOUtils.copyBytes(fis, fos, 4 * 1024, true);
        System.out.println("通过IO流传送文件到HDFS完成");
    }


    /**
     * 通过IO流方式从文件到HDFS获取文件
     *
     * @throws URISyntaxException
     * @throws IOException
     * @throws InterruptedException
     */
    @Test
    public void getFileFromHDFSByIo() throws URISyntaxException, IOException, InterruptedException {
        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.连接hdfs文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");
        //4.创建目标地址
        //注意目标位置不能是个目录，需要文件的名字
        Path readPath = new Path("hdfs://bigdata111:9000/sougou.txt");
        FSDataInputStream fis = fs.open(readPath);

        //5.流对接
        //InputStream       输入
        //OutputStream       输出，System.out表示输出到控制台
        //int bufsize       大小
        //boolean           是否关闭
        IOUtils.copyBytes(fis, System.out, 4 * 1024, true);
        System.out.println("通过IO流传送文件到HDFS完成");
    }


    /**
     * 定位文件块读取
     * IO读取第一块的内容
     */
    @Test
    public void readFileSeek1() throws IOException, URISyntaxException, InterruptedException {

        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");

        //3.输入路劲
        Path path = new Path("hdfs://bigdata111:9000/hadoop-2.7.2.rar");

        FSDataInputStream fis = fs.open(path);

        //4.输出
        FileOutputStream fos = new FileOutputStream("D:\\data\\seekFiles\\A1");

        byte[] buf = new byte[1024];
        //5.流对接
        for (int i = 0; i < 128 * 1024; i++) {
            fis.read(buf);
            fos.write(buf);
        }

        //6.关闭流
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);

    }


    /**
     * 定位文件块读取
     * IO读取第二块的内容
     */
    @Test
    public void readFileSeek2() throws IOException, URISyntaxException, InterruptedException {

        //1.创建配置信息
        Configuration conf = new Configuration();
        //2.获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://bigdata111:9000"), conf, "root");

        //3.输入路劲
        Path path = new Path("hdfs://bigdata111:9000/hadoop-2.7.2.rar");

        FSDataInputStream fis = fs.open(path);

        //4.输出
        FileOutputStream fos = new FileOutputStream("D:\\data\\seekFiles\\A2");

        //5.定位偏移量/offset/游标/读取进度（目的：找到第一快的尾巴，第二快的开头）
        fis.seek(128 * 1024 * 1024);
        //6.流对接
        IOUtils.copyBytes(fis, fos, 1024);

        //7.关闭流
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);

    }


    @Test
    public void writeFile() throws IOException {

        //1.创建配置对象
        Configuration conf = new Configuration();
        //2.输出流
        FileSystem fs = FileSystem.get(conf);
//        FSDataOutputStream fos = fs.create(new Path("D:\\data\\H2.txt"));
        FSDataOutputStream fos = fs.create(new Path("D:\\data\\H.txt"));
        //3.写数据
        fos.write("Andy".getBytes());

        //4.一致性
        fos.flush();

        //5.关闭
        fos.close();

    }
}
